package exchange

import (
	"global/core"
	"fmt"
	"time"
	"github.com/ngaut/log"
	"global/libs/structs"
	"encoding/json"
	"strings"
	"global/libs/exchanges"
	"github.com/garyburd/redigo/redis"
)

const (
	BitzKlineResolution1min = "1min"
)

type BitZKline struct {
	BaseKline
}

func NewBitZKline() KlineInterface {
	return new(BitZKline)
}

func (k *BitZKline) Init(ctx *core.Context, slug string) error {
	k.BaseKline.init(ctx, slug)
	if err := k.loadSymbols(); err != nil {
		return err
	}
	if len(k.symbols) == 0 {
		return fmt.Errorf("init symbols failed, length 0, slug: %s", slug)
	}
	return nil
}

func (k *BitZKline) Run() {
	fmt.Println("symbol length:", len(k.symbols))
	for _, v := range k.symbols {
		go func(symbol structs.Symbol) {
			k.startGetKline(&symbol)
		}(v)
	}
}

// 开始
func (k *BitZKline) startGetKline(symbol *structs.Symbol)  {
	timeTicker := time.NewTicker(20 * time.Second)
	go func() {
		for t := range timeTicker.C {
			_ = t
			k.spider(symbol)
		}
	}()
}

func (k *BitZKline) spider(symbol *structs.Symbol)  {
	symbolStr := fmt.Sprintf("%s_%s", strings.ToLower(symbol.From), strings.ToLower(symbol.To))
	datas, err := k.get(symbol)
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}

	if len(datas) == 0 {
		return
	}

	conn := k.ctx.GetBaseRedis().Get()
	defer conn.Close()

	findLastTime, err := core.GetSpiderKlineLastTime(conn, k.slug, "1min", symbolStr)
	if err != nil{
		log.Errorf("Error: error: %s, last time: %d", err, findLastTime)
		return
	}

	for i := len(datas) - 1; i>=0; i-- {
		loc, _ := time.LoadLocation("Local")
		t, _ := time.ParseInLocation("2006-01-02 15:04:05", datas[i].DateTime, loc)
		tx := t.Local().Unix()
		fx := int64(findLastTime)
		if tx < fx { continue }
		if err := k.saveKlineData(&conn, tx, datas[i], symbol, tx != fx); err != nil {
			log.Fatalf("Error: %s", err)
			return
		}
	}
}

// 保存K线数据
func (k *BitZKline) saveKlineData(conn *redis.Conn,
	lastTime int64,
	kline *exchanges.BitzKline,
	symbol *structs.Symbol,
	isAdd bool) error {

	data := structs.SpiderKline{
		Exchange: 	k.slug,
		From: 		symbol.From,
		To: 		symbol.To,
		DateTime:	lastTime,
		Open: 		kline.Open,
		High: 		kline.High,
		Low:	 	kline.Low,
		Close: 		kline.Close,
		Volume: 	kline.Volume,
	}
	return core.SaveKlineDetailToSymbol(*conn, "1min", data, isAdd)
}


// 获取GET数据
func (k *BitZKline) get(symbol *structs.Symbol) ([]*exchanges.BitzKline, error) {
	url := core.GetBitZUrl("kline")
	body, err := k.BaseKline.get(url, map[string]interface{}{
		"size": 300,
		"symbol": fmt.Sprintf("%s_%s", strings.ToLower(symbol.From), strings.ToLower(symbol.To)),
		"resolution": BitzKlineResolution1min,
	})

	if err != nil {
		return nil, err
	}

	type responseStruct struct {
		exchanges.BitzBaseResponse
		Data		struct{
			Bars 			[]*exchanges.BitzKline	`json:"bars"`
			Resolution 		string					`json:"resolution"`
			Symbol 			string 					`json:"symbol"`
			From 			string 					`json:"from"`
			To 				string 					`json:"to"`
			Size 			int 					`json:"size"`
		}											`json:"data"`
	}

	var response responseStruct
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, err
	}

	return response.Data.Bars, nil
}
